#include "ScannerRuleIMPL.h"
using namespace std;
using namespace stdext;

CScannerRule::IMPL::IMPL()
{
	m_KeyMap = CKeyWordNode::create();
	m_SkipSpaceFunc = 0;
	m_NumberScanFunc = 0;
	m_WordScanFunc = 0;
}

CScannerRule::IMPL::~IMPL()
{

}

int CScannerRule::IMPL::RegisterSpetialToken( const char* pKeyWord, int Type )
{
	LOG("Initialize RegisterSpetialToken keyword:%s type:%d",pKeyWord,Type);

	CKeyWordNodePtr pCurrent = m_KeyMap,pNode;
	while (*pKeyWord)
	{
		if (!(pNode = pCurrent->GetNode(*pKeyWord)))
		{
			pNode = CKeyWordNode::create();
			pCurrent->AddNode(*pKeyWord,pNode);
		}
		pCurrent = pNode;
		++pKeyWord;
	}

	if (pCurrent != m_KeyMap)
	{
		pCurrent->SetAccept(true);
		pCurrent->SetType(Type);
	}
	return 0;
}

CTerminateTokenPtr CScannerRule::IMPL::ScanSpetialToken( CCodePtr pCode )
{
    CKeyWordNodePtr pCurrent = m_KeyMap, pNode;
	char ch;
	pCode->PeekChar(ch);

	if (ch == EOF)
	{
		return CTokenFactory::createToken<CTerminateToken>(TOKEN_EOF);
	}

	while (pNode = pCurrent->GetNode(ch))
	{
		pCurrent = pNode;
		pCode->GetChar(ch);
		pCode->PeekChar(ch);
	}

	if (pCurrent == m_KeyMap)
	{
		return CTerminateTokenPtr();
	}

	if (pCurrent->GetAccept())
	{
		return CTokenFactory::createToken<CTerminateToken>(pCurrent->GetType());
	}
	else
	{
		//BUGBUG
		LOG("Error in ScanSpetialToken");
	}
	return CTerminateTokenPtr();
}

int CScannerRule::IMPL::RegisterSkipSpaceFunc( SkipSpaceFunc func )
{
	LOG("Initialize RegisterWhiteSpace func : %p", func);
	m_SkipSpaceFunc = func;
	return 0;
}

void CScannerRule::IMPL::SkipSpace(CCodePtr pCode )
{
	if (m_SkipSpaceFunc)
	{
		m_SkipSpaceFunc(pCode);
	}

}

int CScannerRule::IMPL::RegisterNumberScanFunc( NumberScanFunc func )
{
    LOG("Initialize RegisterNumberScanFunc func : %p", func);
	m_NumberScanFunc = func;
	return 0;
}

int CScannerRule::IMPL::RegisterWordScanFunc( WordScanFunc func )
{
    LOG("Initialize RegisterWordScanFunc func : %p", func);
	m_WordScanFunc = func;
	return 0;
}

CTerminateTokenPtr CScannerRule::IMPL::ScanNumber( CCodePtr pCode )
{
	if (m_NumberScanFunc)
	{
		return m_NumberScanFunc(pCode);
	}

    return CTerminateTokenPtr();
}

CTerminateTokenPtr CScannerRule::IMPL::ScanWord( CCodePtr pCode )
{
	CTerminateTokenPtr pToken;
	if (m_WordScanFunc)
	{
		pToken = m_WordScanFunc(pCode);
		if (pToken)
		{
			int Type = GetKeyWord(pToken->GetStringValue());
			if (Type)
			{
				pToken->SetType(Type);
			}
		}
	}

	return pToken;
}

int CScannerRule::IMPL::RegisterKeyWord( const char* pKeyWord, int Type )
{
	if (m_KeyWordHash.find(pKeyWord) == m_KeyWordHash.end())
	{
		m_KeyWordHash[pKeyWord] = Type;
	}
	else
	{
		LOG("Warning : CScannerRule::IMPL::RegisterKeyWord Trying to register duplicate keyword");
	}
	return 0;
}

int CScannerRule::IMPL::GetKeyWord( const std::string& strKeyword )
{
	hash_map<string,int>::iterator it = m_KeyWordHash.find(strKeyword);
	if (it == m_KeyWordHash.end())
	{
		return 0;
	}
	else
	{
		return it->second;
	}
}